import { Injectable } from '@nestjs/common';
import { ReflectUtil } from './reflect.util';

/**
 * 对象处理工具类
 * 基于 NestJS 实现 Java 风格的 ObjectUtils
 * 对应 Java: ObjectUtils, CollectUtils
 */
@Injectable()
export class ObjectUtil {
  constructor(private readonly reflectUtil: ReflectUtil) {}

  /**
   * 创建对象实例
   * @param className 类名
   * @returns 对象实例
   */
  create<T = any>(className: string): T {
    return this.reflectUtil.newInstance<T>(className);
  }

  /**
   * 根据参数创建对象实例
   * @param className 类名
   * @param args 构造参数
   * @returns 对象实例
   */
  createWithArgs<T = any>(className: string, ...args: any[]): T {
    return this.reflectUtil.newInstanceWithArgs<T>(className, ...args);
  }

  /**
   * 根据源对象和目标类构建新对象
   * @param source 源对象
   * @param targetClass 目标类
   * @returns 新对象
   */
  build<T = any>(
    source: any,
    targetClass: new (...args: any[]) => T,
  ): T | null {
    if (!source || !targetClass) {
      return null;
    }

    try {
      const target = new targetClass();
      this.copyProperties(source, target);
      return target;
    } catch (error) {
      throw new Error(`Failed to build object: ${error.message}`);
    }
  }

  /**
   * 复制对象属性
   * @param source 源对象
   * @param target 目标对象
   * @returns 目标对象
   */
  copyProperties<T = any>(source: any, target: T): T {
    if (!source || !target) {
      return target;
    }

    try {
      this.reflectUtil.copyFields(source, target);
      return target;
    } catch (error) {
      throw new Error(`Failed to copy properties: ${error.message}`);
    }
  }

  /**
   * 复制指定属性
   * @param source 源对象
   * @param target 目标对象
   * @param fields 要复制的属性名数组
   * @returns 目标对象
   */
  copyPropertiesWithFields<T = any>(
    source: any,
    target: T,
    fields: string[],
  ): T {
    if (!source || !target || !fields) {
      return target;
    }

    try {
      this.reflectUtil.copyFields(source, target, fields);
      return target;
    } catch (error) {
      throw new Error(
        `Failed to copy properties with fields: ${error.message}`,
      );
    }
  }

  /**
   * 转换为指定类型的对象列表
   * @param sourceList 源对象列表
   * @param targetClass 目标类
   * @returns 目标对象列表
   */
  convertList<T = any>(
    sourceList: any[],
    targetClass: new (...args: any[]) => T,
  ): T[] {
    if (!sourceList || !Array.isArray(sourceList)) {
      return [];
    }

    const targetList: T[] = [];
    for (const source of sourceList) {
      try {
        const target = this.build(source, targetClass);
        if (target) {
          targetList.push(target);
        }
      } catch (error) {
        // 忽略转换失败的对象
        console.warn(`Failed to convert object: ${error.message}`);
      }
    }
    return targetList;
  }

  /**
   * 完全转换对象列表
   * @param sourceList 源对象列表
   * @param targetClass 目标类
   * @returns 目标对象列表
   */
  convertListComplete<T = any>(
    sourceList: any[],
    targetClass: new (...args: any[]) => T,
  ): T[] {
    if (!sourceList || !Array.isArray(sourceList)) {
      return [];
    }

    const targetList: T[] = [];
    for (const source of sourceList) {
      try {
        const target = new targetClass();
        this.copyProperties(source, target);
        targetList.push(target);
      } catch (error) {
        // 忽略转换失败的对象
        console.warn(`Failed to convert object completely: ${error.message}`);
      }
    }
    return targetList;
  }

  /**
   * 检查对象是否为空
   * @param obj 要检查的对象
   * @returns 是否为空
   */
  isEmpty(obj: any): boolean {
    return this.reflectUtil.isEmpty(obj);
  }

  /**
   * 检查对象是否不为空
   * @param obj 要检查的对象
   * @returns 是否不为空
   */
  isNotEmpty(obj: any): boolean {
    return this.reflectUtil.isNotEmpty(obj);
  }

  /**
   * 获取对象属性值
   * @param obj 对象
   * @param path 属性路径，支持点号分隔的嵌套属性
   * @param defaultValue 默认值
   * @returns 属性值
   */
  getProperty<T = any>(
    obj: any,
    path: string,
    defaultValue?: T,
  ): T | undefined {
    if (!obj || !path) {
      return defaultValue;
    }

    try {
      const keys = path.split('.');
      let current = obj;

      for (const key of keys) {
        if (current === null || current === undefined) {
          return defaultValue;
        }
        current = current[key];
      }

      return current !== undefined ? current : defaultValue;
    } catch (error) {
      return defaultValue;
    }
  }

  /**
   * 设置对象属性值
   * @param obj 对象
   * @param path 属性路径，支持点号分隔的嵌套属性
   * @param value 属性值
   */
  setProperty(obj: any, path: string, value: any): void {
    if (!obj || !path) {
      return;
    }

    try {
      const keys = path.split('.');
      const lastKey = keys.pop();
      let current = obj;

      for (const key of keys) {
        if (current[key] === null || current[key] === undefined) {
          current[key] = {};
        }
        current = current[key];
      }

      if (lastKey) {
        current[lastKey] = value;
      }
    } catch (error) {
      throw new Error(`Failed to set property ${path}: ${error.message}`);
    }
  }

  /**
   * 删除对象属性
   * @param obj 对象
   * @param path 属性路径，支持点号分隔的嵌套属性
   */
  deleteProperty(obj: any, path: string): void {
    if (!obj || !path) {
      return;
    }

    try {
      const keys = path.split('.');
      const lastKey = keys.pop();
      let current = obj;

      for (const key of keys) {
        if (current[key] === null || current[key] === undefined) {
          return;
        }
        current = current[key];
      }

      if (lastKey && current.hasOwnProperty(lastKey)) {
        delete current[lastKey];
      }
    } catch (error) {
      throw new Error(`Failed to delete property ${path}: ${error.message}`);
    }
  }

  /**
   * 检查对象是否有指定属性
   * @param obj 对象
   * @param path 属性路径，支持点号分隔的嵌套属性
   * @returns 是否有该属性
   */
  hasProperty(obj: any, path: string): boolean {
    if (!obj || !path) {
      return false;
    }

    try {
      const keys = path.split('.');
      let current = obj;

      for (const key of keys) {
        if (
          current === null ||
          current === undefined ||
          !current.hasOwnProperty(key)
        ) {
          return false;
        }
        current = current[key];
      }

      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 获取对象的所有属性名
   * @param obj 对象
   * @returns 属性名数组
   */
  getPropertyNames(obj: any): string[] {
    return this.reflectUtil.getFieldNames(obj);
  }

  /**
   * 获取对象的所有方法名
   * @param obj 对象
   * @returns 方法名数组
   */
  getMethodNames(obj: any): string[] {
    return this.reflectUtil.getMethodNames(obj);
  }

  /**
   * 合并对象
   * @param target 目标对象
   * @param sources 源对象数组
   * @returns 合并后的对象
   */
  merge<T = any>(target: T, ...sources: any[]): T {
    if (!target) {
      target = {} as T;
    }

    for (const source of sources) {
      if (source && typeof source === 'object') {
        this.copyProperties(source, target);
      }
    }

    return target;
  }

  /**
   * 深度合并对象
   * @param target 目标对象
   * @param sources 源对象数组
   * @returns 合并后的对象
   */
  deepMerge<T = any>(target: T, ...sources: any[]): T {
    if (!target) {
      target = {} as T;
    }

    for (const source of sources) {
      if (source && typeof source === 'object') {
        this.deepMergeObject(target, source);
      }
    }

    return target;
  }

  /**
   * 深度合并单个对象
   * @param target 目标对象
   * @param source 源对象
   */
  private deepMergeObject(target: any, source: any): void {
    for (const key in source) {
      if (source.hasOwnProperty(key)) {
        const sourceValue = source[key];
        const targetValue = target[key];

        if (this.isObject(sourceValue) && this.isObject(targetValue)) {
          this.deepMergeObject(targetValue, sourceValue);
        } else {
          target[key] = JSON.parse(JSON.stringify(sourceValue));
        }
      }
    }
  }

  /**
   * 检查是否为对象
   * @param obj 要检查的值
   * @returns 是否为对象
   */
  private isObject(obj: any): boolean {
    return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
  }

  /**
   * 对象转数组
   * @param obj 对象
   * @returns 数组
   */
  toArray(obj: any): any[] {
    if (!obj) {
      return [];
    }

    if (Array.isArray(obj)) {
      return obj;
    }

    if (typeof obj === 'object') {
      return Object.values(obj);
    }

    return [obj];
  }

  /**
   * 数组转对象
   * @param array 数组
   * @param keyField 作为键的字段名
   * @returns 对象
   */
  toObject(array: any[], keyField: string): Record<string, any> {
    if (!array || !Array.isArray(array)) {
      return {};
    }

    const obj: Record<string, any> = {};
    for (const item of array) {
      if (item && typeof item === 'object' && item[keyField] !== undefined) {
        obj[item[keyField]] = item;
      }
    }

    return obj;
  }

  /**
   * 过滤对象属性
   * @param obj 对象
   * @param predicate 过滤条件函数
   * @returns 过滤后的对象
   */
  filterProperties(
    obj: any,
    predicate: (key: string, value: any) => boolean,
  ): any {
    if (!obj || typeof obj !== 'object') {
      return {};
    }

    const filtered: any = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key) && predicate(key, obj[key])) {
        filtered[key] = obj[key];
      }
    }

    return filtered;
  }

  /**
   * 映射对象属性
   * @param obj 对象
   * @param mapper 映射函数
   * @returns 映射后的对象
   */
  mapProperties(obj: any, mapper: (key: string, value: any) => any): any {
    if (!obj || typeof obj !== 'object') {
      return {};
    }

    const mapped: any = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        mapped[key] = mapper(key, obj[key]);
      }
    }

    return mapped;
  }
}
